#include "ParseBAT.h"
#include "ParseTS_Head.h"
#include "main.h"
#include "ParseType.h"

static int bat_i,bat_n,bat_l;
static unsigned int BAT_CRC[4096];
static unsigned char BAT_Long_Table[1200];
static unsigned char CountBat;

void TSBAT_Section(unsigned char BATtable[1200], int SectionPosition, TS_BAT *NewBatPoint)
{
    int BAT_Length = 0;
	int SectionCount = 0;
	unsigned char descriptor[204];

    BAT_Length = NewBatPoint->section_length + 3;

        for (SectionPosition; SectionPosition < BAT_Length - 4; SectionPosition += 6)
	{
		NewBatPoint->BAT_Section[SectionCount].transport_stream_id = (BATtable[SectionPosition] << 8) 
                        | BATtable[SectionPosition + 1];
		NewBatPoint->BAT_Section[SectionCount].original_network_id = (BATtable[SectionPosition + 2] << 8) 
                        | BATtable[SectionPosition + 3];
		NewBatPoint->BAT_Section[SectionCount].reserved_future_use = BATtable[SectionPosition + 4] >> 4;
		NewBatPoint->BAT_Section[SectionCount].transport_descriptors_length = (BATtable[SectionPosition + 4] & 0x0f) << 8 
                        | BATtable[SectionPosition + 5];

        if(NewBatPoint->BAT_Section[SectionCount].transport_descriptors_length != 0)
        {
           memcpy(NewBatPoint->BAT_Section[SectionCount].descriptor, BATtable+SectionPosition + 6, 
                        NewBatPoint->BAT_Section[SectionCount].transport_descriptors_length);
			SectionPosition += NewBatPoint->BAT_Section[SectionCount].transport_descriptors_length;
        }
        SectionCount++;    
    }
}

void  TSBAT_Table(unsigned char BATtable[1200],TS_BAT *NewBatPoint)
{
    int BAT_Length = 0;
    int BATpoint = 0;


    NewBatPoint->table_id = BATtable[0];
    NewBatPoint->section_syntax_indicator = BATtable[1] >> 7;
    NewBatPoint->reserved_future_use1 = (BATtable[1] >> 6) & 0X01;
    NewBatPoint->reserved1 = (BATtable[1] >> 4) & 0x03;
    NewBatPoint->section_length = (BATtable[1] & 0x0f) << 8 | BATtable[2];
    NewBatPoint->bouquet_id = (BATtable[3] << 8) | BATtable[4];
    NewBatPoint->reserved2 = (BATtable[5] >> 6) & 0x03;
    NewBatPoint->version_number = (BATtable[5] >> 1) & 0x1f;
    NewBatPoint->current_next_indicator = BATtable[5] & 0x01;
    NewBatPoint->section_number = BATtable[6];
    NewBatPoint->last_section_number = BATtable[7];
    NewBatPoint->reserved_future_use2 = BATtable[8] >> 4;
    NewBatPoint->bouquet_descriptors_length = (BATtable[8] & 0x0f) << 8 | BATtable[9];

    if(NewBatPoint->bouquet_descriptors_length != 0)
    {
       memcpy(NewBatPoint->descriptor, BATtable+10, NewBatPoint->bouquet_descriptors_length);
    }

    BATpoint = 10 + NewBatPoint->bouquet_descriptors_length;
    NewBatPoint->reserved_future_use3 = BATtable[BATpoint] >> 4;
    NewBatPoint->transport_stream_loop_length = (BATtable[BATpoint] & 0x0f) << 8 | BATtable[BATpoint + 1];

    if(NewBatPoint->transport_stream_loop_length != 0)
    {
      TSBAT_Section(BATtable, BATpoint + 2, NewBatPoint);
    }

    BAT_Length = NewBatPoint->section_length + 3;
    NewBatPoint->CRC_32 = (BATtable[BAT_Length - 4] << 24) | (BATtable[BAT_Length - 3] << 16)
	        | (BATtable[BAT_Length - 2] << 8) | BATtable[BAT_Length - 1];

	if(NewBatPoint->section_length > 188)
	{
		bat_l = NewBatPoint->section_length;
	}


	if(NewBatPoint->section_length < 188 || ((bat_l / 188) == bat_n && NewBatPoint->CRC_32 != 0))
	{
		if(bat_i == 0)
		{
			NewBatPoint->next = NULL;
			NewBatPoint->Previous = BatPoint;
			BatPoint->next = NewBatPoint;
			BatPoint = BatPoint->next;

			BAT_CRC[bat_i] = NewBatPoint->CRC_32;

			bat_i ++;
		}else
		{
			for(int p = 0; p < bat_i; p++)
			{
				if(BAT_CRC[p] == NewBatPoint->CRC_32)
				{
					return;
				}
			}
				NewBatPoint->next = NULL;
				NewBatPoint->Previous = BatPoint;
				BatPoint->next = NewBatPoint;
				BatPoint = BatPoint->next;

				BAT_CRC[bat_i] = NewBatPoint->CRC_32;

				bat_i ++;
		}
	}
}

void ParseTS_BAT_1(int TsPackage_len,TS_Package_Head TS_PackageBATHead)
{
    TS_BAT TS_PackageBAT = {0};
    unsigned char BATtable[204] = {0};
    TS_BAT *NewBatPoint = (TS_BAT *)malloc(sizeof(TS_BAT));

    CountBat = TS_PackageBATHead.continuity_counter;


    TSBAT_Table(BATtable, NewBatPoint);

	bat_n = 0;	
	memset(BAT_Long_Table, 0, 1200);
	memcpy(BAT_Long_Table, TSdata+5, TsPackage_len-5);
}

void ParseTS_BAT_0(int TsPackage_len,TS_Package_Head TS_PackageBATHead)
{
    TS_BAT TS_PackageBAT = {0};
	unsigned char BATtable[204] = {0};

    memcpy(BATtable, TSdata+4, TsPackage_len-4);

	if(bat_n == 0 && CountBat+1 == TS_PackageBATHead.continuity_counter)
	{
		memcpy(BAT_Long_Table+183, BATtable, TsPackage_len-4);
		CountBat++;
		bat_n++;
	}else if(CountBat+1 == TS_PackageBATHead.continuity_counter)
	{
		memcpy(BAT_Long_Table+(183+(184*bat_n)), BATtable, TsPackage_len-4);
		CountBat++;
		bat_n++;
	}

	if((bat_l / 188) == bat_n)
	{
		TS_BAT *NewBATPoint = (TS_BAT *)malloc(sizeof(TS_BAT));
		TSBAT_Table(BAT_Long_Table, NewBATPoint);
		bat_n = 0;
		memset(BAT_Long_Table, 0, 1200);
	}
}